home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / system / srouted-.000 / srouted- / srouted-0.1pl1 / error.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-17  |  13.7 KB  |  412 lines

  1. /* error.c -- some rudimentary error support */
  2.  
  3. /*
  4.  *  srouted -- silent routing daemon
  5.  *  Copyright (C) 1995 Kevin Buhr
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Id: error.c,v 1.5 1995/02/17 17:43:27 buhr Exp $";
  24. #endif /* not lint */
  25.  
  26. #include "defs.h"
  27. #include "table.h"
  28. #include "error.h"
  29.  
  30. #include <stdio.h>
  31. #include <stdarg.h>
  32. #include <errno.h>
  33. #include <netinet/in.h>
  34. #include <arpa/inet.h>
  35.  
  36.  
  37. enum er_form {
  38.    ERCF_,    /* void */
  39.    ERCF_E,    /* int errno */
  40.    ERCF_IE,    /* int ioctl, int errno */
  41.    ERCF_RF,    /* struct rip *rip, int length, struct tb_address *from */
  42.    ERCF_RFE,    /* struct rip *rip, int length, struct tb_address *from, int entry */
  43.    ERCF_RFEM,    /* struct rip *rip, int length, struct tb_address *from, int entry, int metric */
  44.    ERCF_RFEMR,    /* struct rip *rip, int length, struct tb_address *from, int entry, int metric, int route */
  45.    ERCF_I,    /* struct iface *iface */
  46.    ERCF_IR,    /* struct iface *iface, struct tb_route *route */
  47.    ERCF_ID,    /* struct iface *iface, struct tb_address *dest */
  48.    ERCF_SS,    /* int size, int size */
  49.    ERCF_A,    /* struct tb_address *address */
  50.    ERCF_P,    /* int port */
  51.    ERCF_T,    /* no args---dump routing table */
  52.    ERCF_TTT,    /* int now, int next, int pause */
  53.    ERCF_R,    /* int route */
  54.    ERCF_LAST
  55. };
  56.  
  57. #define ERCN_MASK    0xF000
  58. #define ERCN_SHIFT    12
  59. #define ERCN_0        0x0000
  60. #define ERCN_1        0x1000
  61. #define ERCN_2        0x2000
  62. #define ERCN_3        0x3000
  63. #define ERCN_4        0x4000
  64.  
  65. static struct er_table {
  66.    enum er_code ert_code;
  67.    short ert_form;
  68.    char *ert_text;
  69. } er_table[] = {
  70.    ERC_NOERROR,    ERCF_,        NULL,
  71.  
  72. /* input.c */
  73.    ERCIN_BADFROM, ERCF_,    "Received RIP from invalid address",
  74.    ERCIN_VERS0, ERCF_RF,    "Received RIP packet with version zero",
  75.    ERCIN_CZ,    ERCF_RF,    "Received RIP packet with bad header reserved areas",
  76.    ERCIN_CZE,    ERCF_RFE,    "Received RIP packet with bad entry reserved areas",
  77.    ERCIN_CMD0,    ERCF_RF,    "Received RIP packet with command code zero",
  78.    ERCIN_UNKCMD, ERCF_RF,    "Received RIP packet with unknown command code",
  79.    ERCIN_CMD34,    ERCF_RF,    "Received RIP packet using obsolete trace commands",
  80.    ERCIN_CMD5,    ERCF_RF,    "Received RIP packet using Sun's reserved command code 5",
  81.    ERCIN_UNKAF,    ERCF_RFE,    "Received RIP packet entry for unknown address family",
  82.    ERCIN_RESPPORT, ERCF_RF,    "Received RIP response from invalid port",
  83.    ERCIN_RESPREMOTE, ERCF_RF,    "Received RIP response from remote source",
  84.    ERCIN_BADMETRIC, ERCF_RFE,    "Received RIP response entry with invalid metric",
  85.    ERCIN_BADADDR, ERCF_RFE,    "Received RIP response entry with bad address",
  86.    ERCIN_RTFULL, ERCF_,        "Route table full",
  87.    ERCIN_RTSUPER, ERCF_A,    "Received unsubnetted route for subnetted network",
  88.  
  89. /* output.c */
  90.    ERCOUT_SENDTO, ERCF_E,    "\"sendto\" call failed",
  91.    ERCOUT_FULLOUT, ERCF_,    "Filled output buffer",
  92.    ERCOUT_BADIFACE, ERCF_I,    "Couldn't broadcast to interface",
  93.  
  94. /* kernel.c */
  95.    ERCKR_NOIPSOCK, ERCF_E,    "Failed to open internet datagram socket",
  96.    ERCKR_IOCTL,    ERCF_IE,    "Interface configuration IOCTL failed",
  97.    ERCKR_IFFULL, ERCF_,        "Insufficient interface configuration entries to store interface configuration",
  98.    ERCKR_XADDRT, ERCF_E,    "Failed to add route",
  99.    ERCKR_XDELRT, ERCF_E,    "Failed to delete route",
  100.  
  101. /* table.c */
  102.    ERCTB_RTFULL, ERCF_,        "Route table full",
  103.    ERCTB_RTDUP,    ERCF_IR,    "Two interfaces had same destination",
  104.    ERCTB_INVDEST, ERCF_ID,    "Interface destination not a valid IP address",
  105.    ERCTB_BADSUPER, ERCF_A,    "Subnetted net appeared as destination in route table",
  106.  
  107. /* driver.c */
  108.    ERCDR_SYNTAX, ERCF_,        "Syntax: srouted [-t ...]",
  109.    ERCDR_NOTROOT, ERCF_,    "Must be root",
  110.    ERCDR_BIGRIP, ERCF_SS,    "Received oversized packet",
  111.    ERCDR_SELECT, ERCF_E,    "\"select\" call failed",
  112.    ERCDR_ADDRSIZE, ERCF_SS,    "Packet source address had bad size",
  113.    ERCDR_SOCKET, ERCF_E,        "\"socket\" call failed",
  114.    ERCDR_FCNTL,    ERCF_E,            "\"fcntl(O_NONBLOCK)\" failed",
  115.    ERCDR_SSOPT, ERCF_E,            "\"setsockopt(SO_BROADCAST)\" failed",
  116.    ERCDR_BIND,    ERCF_E,            "\"bind\" call failed",
  117.    ERCDR_RECVFROM, ERCF_E,      "\"recvfrom\" call failed",
  118.    ERCDR_GETSERV, ERCF_,        "Failed to get \"route\" service by name",
  119.  
  120. /* notification/tracing codes start here */
  121. /* driver.c */
  122.    ERCDR_USINGPORT, ERCF_P | ERCN_2,    "[driver] Using \"route\" port",
  123.    ERCDR_GETIFCONF, ERCF_  | ERCN_1,    "[driver] Getting current interface configuration",
  124.    ERCDR_INITROUTE, ERCF_  | ERCN_1,          "[driver] Constructing initial route table entries",
  125.    ERCDR_GETTABLE, ERCF_   | ERCN_1,    "[driver] Broadcasting for copy of whole table",
  126.    ERCDR_DUMPROUTE, ERCF_T | ERCN_0,    "[driver] dumproute==1, dumping routing table",
  127.    ERCDR_SCHED,    ERCF_TTT   | ERCN_4,    "[driver] \"select\" loop scheduling status",
  128.    ERCDR_TIMEOUT, ERCF_    | ERCN_4,    "[driver] \"select\" loop timed out",
  129.    ERCDR_GOTINPUT, ERCF_   | ERCN_4,    "[driver] \"select\" loop got input",
  130.  
  131. /* input.c */
  132.    ERCIN_GOTINPUT, ERCF_   | ERCN_4,    "[input] Processing received packet",
  133.    ERCIN_IGNOREREQUEST, ERCF_RF|ERCN_4, "[input] Ignoring request received on \"route\" port",
  134.    ERCIN_GOTREQUEST, ERCF_RF|ERCN_1,    "[input] Received a request packet",
  135.    ERCIN_REQWHOLE, ERCF_   | ERCN_2,    "[input] Responding to request for whole routing table",
  136.    ERCIN_REQENTRY, ERCF_RFEM|ERCN_3,    "[input] Processing request entry",
  137.    ERCIN_REQANSWER, ERCF_  | ERCN_2,    "[input] Responding to normal request",
  138.    ERCIN_GOTRESPONSE, ERCF_RF|ERCN_2,   "[input] Received a response packet",
  139.    ERCIN_RESENTRY, ERCF_RFEMR|ERCN_3,   "[input] Processing response entry",
  140.    ERCIN_IGNOREHOST, ERCF_R| ERCN_4,    "[input] Ignoring host route, had net route",
  141.    ERCIN_RESADDED, ERCF_R  | ERCN_4,    "[input] Added route from response packet",
  142.    ERCIN_HADROUTE, ERCF_   | ERCN_4,    "[input] Comparing new with existing route",
  143.    ERCIN_REPEATROUTE, ERCF_| ERCN_4,    "[input] New and existing are identical, updating timer",
  144.    ERCIN_RESDELETED, ERCF_R| ERCN_4,    "[input] Deleting route based on response entry",
  145.    ERCIN_RESIGNORED, ERCF_ | ERCN_4,    "[input] Response entry route ignored",
  146.  
  147. /* output.c */
  148.    ERCOUT_SENDING, ERCF_RF | ERCN_2,    "[output] Sending a RIP",
  149.    ERCOUT_UPDATE, ERCF_    | ERCN_4,    "[output] Update triggered and ignored",
  150.    ERCOUT_SENDTABLE, ERCF_A| ERCN_1,    "[output] Sending a copy of whole routing table",
  151.    ERCOUT_GETTABLE, ERCF_ID| ERCN_1,    "[output] Broadcasting request for whole table",
  152.  
  153. /* kernel.c */
  154.    ERCKR_DELRT,    ERCF_R        | ERCN_4,    "[kernel] Deleted kernel route",
  155.    ERCKR_ADDRT, ERCF_R        | ERCN_4,    "[kernel] Added kernel route",
  156.  
  157. /* table.c */
  158.    ERCTB_ADDEDSUPER, ERCF_R| ERCN_2,    "[table] Added dummy supernet route",
  159.    ERCTB_IFDEFAULT, ERCF_ID| ERCN_2,    "[table] Constructed default route for interface",
  160.    ERCTB_ADDRT,    ERCF_R        | ERCN_1,    "[table] Added route",
  161.    ERCTB_DELRT,    ERCF_R        | ERCN_1,    "[table] Deleted route",
  162.    ERCTB_KEPTRT, ERCF_R    | ERCN_1,    "[table] Keeping dead route",
  163.    ERCTB_KILLRT, ERCF_R    | ERCN_1,    "[table] Killing dead route",
  164.  
  165. /* timer.c */
  166.    ERCTM_SETTO,    ERCF_R        | ERCN_4,    "[timer] Setting timeout timer",
  167.    ERCTM_SETGC, ERCF_R        | ERCN_4,    "[timer] Setting garbage collection timer",
  168.    ERCTM_KILL, ERCF_R        | ERCN_4,    "[timer] Killing timers",
  169.    ERCTM_TIMEOUT, ERCF_R   | ERCN_2,    "[timer] Timeout timer expired",
  170.    ERCTM_GARBCOLL, ERCF_R  | ERCN_2,    "[timer] Garbage collection timer expired",
  171.    ERCTM_NETO,    ERCF_R        | ERCN_4,    "[timer] Next event is \"timeout\"",
  172.    ERCTM_NEGC,    ERCF_R        | ERCN_4,    "[timer] Next event is \"garbage collection\"",
  173.    ERCTM_NENONE,ERCF_        | ERCN_1,    "[timer] No events pending",
  174.  
  175.    ERC_LAST,    ERCF_,                "Unknown error code received!!!"
  176. };
  177.  
  178. static char *er_severity[] = { "note", "fatal error", "warn", "weakwarn", "note" };
  179.  
  180.  
  181. /*
  182.  *      Produce dot-form of a sockaddr
  183.  */
  184.  
  185. static char *er_satoa( struct sockaddr *sa )
  186. {
  187.    return( inet_ntoa( ((struct sockaddr_in *) sa)->sin_addr ) );
  188. }
  189.  
  190.  
  191. /*
  192.  *    Dump RIP parts
  193.  */
  194.  
  195. void er_dumprip( struct rip *rip, int length, struct tb_address *from )
  196. {
  197.    fprintf(stderr, "    RIP packet of length %d address %s port %d:\n    RIP cmd %s(%d) vers %d\n",
  198.        length, er_satoa( &from->tba_addr ), from->tba_port,
  199.        rip->rip_cmd == RIPCMD_REQUEST ? "REQUEST"
  200.        : rip->rip_cmd == RIPCMD_RESPONSE ? "RESPONSE"
  201.        : "",
  202.        rip->rip_cmd, rip->rip_vers);
  203. }
  204. void er_dumpripe( struct rip *rip, int entry )
  205. {
  206.    fprintf(stderr, "      entry %d dest %s (af=%d) metric %lu\n",
  207.        entry,
  208.        er_satoa( &rip->rip_nets[entry].rip_dst ),
  209.        ntohs(rip->rip_nets[entry].rip_dst.sa_family),
  210.        ntohl(rip->rip_nets[entry].rip_metric) );
  211. }
  212.  
  213.  
  214. /*
  215.  *    Log an error
  216.  */
  217.  
  218. void er_log( int level, enum er_code code, ... )
  219. {
  220.    struct tb_address *address;
  221.    struct tb_route *route;
  222.    struct tb_iface *iface;
  223.    struct rip *rip;
  224.    struct er_table *error;
  225.    int errno, ioctl, length, length2, rti;
  226.    time_t now, next, pause;
  227.    short form;
  228.  
  229.    va_list arg;
  230.    va_start( arg, code );
  231.  
  232.    if( level > g_tracelevel )
  233.       return;
  234.  
  235.    for( error=&er_table[0]; error->ert_code!=ERC_LAST; error++ ) {
  236.       if( error->ert_code == code )
  237.      break;
  238.    }
  239.  
  240.    if( error->ert_code == ERC_LAST )
  241.       level = ERL_DIE;
  242.  
  243.    if( level == ERL_NOTE
  244.       && ((error->ert_form & ERCN_MASK) >> ERCN_SHIFT) > g_tracenlevel )
  245.       return;
  246.  
  247.    form = error->ert_form & ~ERCN_MASK;
  248.  
  249.    fprintf( stderr, "srouted %s: %s",
  250.        er_severity[level+1],
  251.        error->ert_text );
  252.  
  253.    switch( form ) {
  254.  
  255.    case ERCF_:
  256.       fprintf(stderr, "\n");
  257.       break;
  258.  
  259.    case ERCF_E:
  260.       fprintf(stderr, ": %s\n", strerror( va_arg(arg, int) ) );
  261.       break;
  262.  
  263.    case ERCF_IE:
  264.       ioctl=va_arg(arg,int);
  265.       errno=va_arg(arg,int);
  266.  
  267.       fprintf(stderr, ": ioctl %d: %s\n", ioctl, strerror( errno ) );
  268.       break;
  269.  
  270.    case ERCF_RF:
  271.    case ERCF_RFE:
  272.    case ERCF_RFEM:
  273.    case ERCF_RFEMR:
  274.       rip = va_arg( arg, struct rip * );
  275.       length = va_arg( arg, int );
  276.       address = va_arg( arg, struct tb_address * );
  277.       fprintf( stderr, ":\n");
  278.       er_dumprip( rip, length, address );
  279.       if( form != ERCF_RF ) {
  280.      er_dumpripe( rip, va_arg( arg, int ) );
  281.      if( form != ERCF_RFE ) {
  282.         fprintf( stderr, "    new cost %d\n", va_arg( arg, int ) );
  283.         if( form != ERCF_RFEM ) {
  284.            rti = va_arg( arg, int );
  285.            if( rti == -1 ) {
  286.           fprintf( stderr, "    no existing route known\n" );
  287.            } else {
  288.           er_dumproute( rti );
  289.            }
  290.         }
  291.      }
  292.       }
  293.       break;
  294.  
  295.    case ERCF_ID:
  296.       iface = va_arg( arg, struct tb_iface * );
  297.       address = va_arg( arg, struct tb_address * );
  298.       fprintf( stderr, ": iface %s, dest %s\n",
  299.           iface->tbif_dev,
  300.           er_satoa( &address->tba_addr ) );
  301.       break;
  302.  
  303.    case ERCF_I:
  304.       iface = va_arg( arg, struct tb_iface * );
  305.       fprintf( stderr, ": iface %s\n",
  306.           iface->tbif_dev );
  307.       break;
  308.  
  309.    case ERCF_IR:
  310.       iface = va_arg( arg, struct tb_iface * );
  311.       route = va_arg( arg, struct tb_route * );
  312.       fprintf( stderr, ": iface-1 %s, iface-2 %s, route %s\n",
  313.           iface->tbif_dev,
  314.           route->tbrt_iface == -1 ? "Oops!" :
  315.                 tb_iface[route->tbrt_iface].tbif_dev,
  316.           er_satoa( &address->tba_addr ) );
  317.       break;
  318.  
  319.    case ERCF_SS:
  320.       length = va_arg( arg, int );
  321.       length2 = va_arg( arg, int );
  322.       fprintf( stderr, ": got %d, expected %d\n", length, length2 );
  323.       break;
  324.  
  325.    case ERCF_A:
  326.       address = va_arg( arg, struct tb_address * );
  327.       fprintf( stderr, ": address %s\n",
  328.           er_satoa( &address->tba_addr ) );
  329.       break;
  330.  
  331.    case ERCF_P:
  332.       fprintf(stderr, ": port %hu\n", va_arg( arg, unsigned short) );
  333.       break;
  334.  
  335.    case ERCF_T:
  336.       fprintf(stderr,":\n");
  337.       er_dumproute( -1 );  /* dump the routing table */
  338.       break;
  339.  
  340.    case ERCF_R:
  341.       fprintf(stderr,":\n");
  342.       er_dumproute( va_arg( arg, int ) );  /* dump one route entry */
  343.       break;
  344.  
  345.    case ERCF_TTT:
  346.       now = va_arg( arg, time_t );
  347.       next = va_arg( arg, time_t );
  348.       pause = va_arg( arg, time_t );
  349.       fprintf(stderr, ": now=%ds, next=%ds, pause=%ds\n",
  350.           (int) now, (int) next, (int) pause);
  351.       break;
  352.  
  353.    default:
  354.       break;  /* this is an error of course, but let's ignore it */
  355.    }
  356.  
  357.    if( level == ERL_DIE ) {
  358.       exit(1);
  359.    }
  360.  
  361. }
  362.  
  363.  
  364. /*
  365.  *    Dump ONE route table row
  366.  */
  367.  
  368. static void er_dumparoute( int i )
  369. {
  370.    fprintf(stderr, "  %15.15s ", er_satoa( &tb_route[i].tbrt_dst ) );
  371.    fprintf(stderr, "%15.15s ", er_satoa( &tb_route[i].tbrt_gateway ) );
  372.    fprintf(stderr, "%15.15s ", er_satoa( &tb_route[i].tbrt_mask ) );
  373.    fprintf(stderr, "%04X    %5d    %8.8s\n",
  374.        tb_route[i].tbrt_flags,
  375.        tb_route[i].tbrt_metric,
  376.        tb_route[i].tbrt_iface != -1 ?
  377.        tb_iface[tb_route[i].tbrt_iface].tbif_dev :
  378.        "none" );
  379. }
  380.  
  381.  
  382. /*
  383.  *    Dump the internal routing table
  384.  */
  385.  
  386. void er_dumproute( int rti )
  387. {
  388.    int i;
  389.  
  390.    fprintf(stderr, "  Destination     Gateway         Mask            Flags   Metric    Iface\n");
  391.  
  392.    if( rti == -1 ) {
  393.       for( i=0; i<TB_ROUTE_SIZE; i++ ) {
  394.      if( (tb_route[i].tbrt_flags & TBRTF_USED)==0 )
  395.         continue;
  396.      er_dumparoute( i );
  397.       }
  398.    } else {
  399.       er_dumparoute( rti );
  400.    }
  401. }
  402.  
  403.  
  404. /*
  405.  *    Notify user of trace level change
  406.  */
  407.  
  408. void er_tracechange( void )
  409. {
  410.    fprintf(stderr,"srouted note: [error] TRACE LEVEL CHANGE: tracelevel=%d, tracenlevel=%d\n", g_tracelevel, g_tracenlevel);
  411. }
  412.